package com.shycloud.mido.organ.service.impl;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.happy.zebra.admin.api.entity.SysActLogZebra;
import com.happy.zebra.admin.api.feign.AdminFeignService;
import com.shycloud.mido.common.core.constant.CommonConstants;
import com.shycloud.mido.common.core.exception.BusinessException;
import com.shycloud.mido.common.core.util.R;
import com.shycloud.mido.common.security.util.SecurityUtils;
import com.shycloud.mido.common.util.SnowFlakeUtil;
import com.shycloud.mido.member.api.entity.*;
import com.shycloud.mido.member.api.util.Constant;
import com.shycloud.mido.organ.api.dto.JoyMasterDTO;
import com.shycloud.mido.organ.api.entity.LineProductUpdateRecord;
import com.shycloud.mido.organ.api.entity.MemberActivateEntity;
import com.shycloud.mido.organ.api.entity.MemberEntity;
import com.shycloud.mido.organ.api.entity.MemberRole;
import com.shycloud.mido.organ.api.entity.OptOrg;
import com.shycloud.mido.organ.api.enums.MessageCodeEnum;
import com.shycloud.mido.organ.api.feign.RemoteMemberService;
import com.shycloud.mido.organ.api.feign.RemoteOptService;
import com.shycloud.mido.organ.api.vo.OrgGoodsVO;
import com.shycloud.mido.organ.mapper.LineProductUpdateRecordMapper;
import com.shycloud.mido.organ.mapper.MemberActivateMapper;
import com.shycloud.mido.organ.mapper.MemberMapper;
import com.shycloud.mido.organ.mapper.MemberRoleMapper;
import com.shycloud.mido.organ.mapper.OptOrgMapper;
import com.shycloud.mido.organ.mapper.OrganizationMapper;
import com.shycloud.mido.organ.service.MemberActivatedService;
import com.shycloud.mido.organ.service.MemberService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
@AllArgsConstructor
public class MemberActivatedServiceImpl extends
		ServiceImpl<MemberActivateMapper, MemberActivateEntity> implements MemberActivatedService {

	/** 纠错大师激活 mapper */
	private MemberActivateMapper memberActivateMapper;
	private LineProductUpdateRecordMapper lineProductUpdateRecordMapper;
	/** 机构 mapper */
	private OrganizationMapper organizationMapper;
	/** feign member Service */
	private RemoteMemberService remoteMemberService;
	/** feign member Service */
	private com.shycloud.mido.member.api.feign.RemoteMemberService remoteMemberServiceMini;
	/** feign opt Service */
	private RemoteOptService remoteOptService;
	/** Member mapper */
	private MemberMapper memberMapper;
	/** 用户 service */
	private MemberService memberService;
	private OptOrgMapper optOrgMapper;
	/** 会员模块 mapper */
	private MemberRoleMapper memberRoleMapper;
	/** admin 模块 feign */
	private final AdminFeignService adminFeignService;

	private final com.shycloud.mido.opter.api.feign.RemoteOptService remoteOptServiceV2;


	@Override
	@Transactional(rollbackFor = Exception.class)
	public R addActivation(String udid, String memberId, int duration) {
		//查询会员是否已经激活，如果已经激活，返回还剩多长时间过期
		R status = isMaster(memberId);
		Map statusMap = (Map) status.getData();

		//查询会员激活记录
		//List<JoyMasterDTO> masterList = memberActivateMapper.selectActivisionByMemberId(memberId);

		if (true == ((boolean) statusMap.get("status"))) {
			//说明该会员当前已在激活状态
			Map returnMap = new HashMap();
			returnMap.put("updateResult", Boolean.FALSE);
			returnMap.put("daysLeft", (Long) statusMap.get("daysLeft"));
			returnMap.put("msg", "该用户已有硬件权限！");
			return new R(CommonConstants.FAIL, "该用户已有硬件权限！", returnMap);
		} else {
			MemberActivateEntity entity = new MemberActivateEntity();

			//entity.setActvCode(ActivationCodeUtil.generateGiftCode("2r"));
			entity.setActvCode(IdUtil.randomUUID().replaceAll("-", ""));
			entity.setUdid(udid);
			entity.setMemberId(memberId);
			entity.setDuration(duration);
			entity.setStatus("1");
			entity.setStartTime(LocalDateTime.now());
			entity.setSpecialType(2);
			entity.setType("1");

			memberActivateMapper.insert(entity);

			Map returnMap = new HashMap();
			returnMap.put("updateResult", Boolean.FALSE);
			returnMap.put("msg", "激活成功");

			return new R(CommonConstants.SUCCESS, "激活成功", returnMap);
		}
	}

	private Boolean haveRepeat(String code) {
		QueryWrapper queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("actv_code", code);
		if (this.list(queryWrapper).size() > 0) {
			return true;
		} else {
			return false;
		}
	}

	//总部延续体验
	@Override
	@Transactional(rollbackFor = Exception.class)
	public R delayHardwareVip(String memberId, String endTime, int duration) {

		MemberActivateEntity entity = new MemberActivateEntity();
		String code = "TY" + IdUtil.simpleUUID().substring(0, 8).toUpperCase();
		while (haveRepeat(code)) {
			code = "TY" + IdUtil.simpleUUID().substring(0, 8).toUpperCase();
		}
		entity.setActvCode(code);
		entity.setMemberId(memberId);
		entity.setDuration(duration);
		entity.setStatus("1");
		DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		LocalDateTime startTime = LocalDateTime.parse(endTime, dateTimeFormatter);
		entity.setStartTime(startTime);
		entity.setSpecialType(2);
		entity.setType("1");
		//只有总部可以续费体验
		entity.setOptrId(999999);

		memberActivateMapper.insert(entity);

		Map returnMap = new HashMap();
		returnMap.put("updateResult", Boolean.FALSE);
		returnMap.put("msg", "激活成功");

		return new R(CommonConstants.SUCCESS, "激活成功", returnMap);
	}

	/**
	 * 开通纠错大师体验
	 *
	 * @param udid
	 * @param memberId
	 * @param duration
	 * @param orgId
	 * @param optId
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public R activateByDuration(String udid, String memberId, int duration, String orgId,
			String optId) {

		//查询会员是否已经激活，如果已经激活，返回还剩多长时间过期
		R status = isMaster(memberId);
		Map statusMap = (Map) status.getData();

		//查询会员激活记录
		//status: 0-未激活, 1-已激活, 2-已过期
		if ((int) statusMap.get("status") == 1) {

			// 计算到期时间
			List<MemberActivateEntity> activateEntities = memberActivateMapper
					.selectList(new QueryWrapper<MemberActivateEntity>()
							.eq("member_id", memberId).orderByDesc("start_time"));
			Map returnMap = new HashMap();

			if (activateEntities.stream().anyMatch(x -> x.getDuration() == 0)) {

				returnMap.put("updateResult", Boolean.FALSE);
				returnMap.put("msg", "该用户已经是永久会员，无需激活！");
				return new R(CommonConstants.FAIL, "该用户已经是永久会员，无需激活！", returnMap);
			}

			//循环取到期时间最后的
			LocalDateTime endTime = activateEntities.get(0).getStartTime()
					.plusDays(activateEntities.get(0).getDuration());

			for (MemberActivateEntity memberActivateEntity : activateEntities) {
				//循环取到期时间最后的
				if (endTime.isBefore(memberActivateEntity.getStartTime()
						.plusDays(memberActivateEntity.getDuration()))) {
					endTime = memberActivateEntity.getStartTime()
							.plusDays(memberActivateEntity.getDuration());
				}
			}

			MemberActivateEntity memberActivateEntity = activateEntities.get(0);

			//没过期的场合，直接续期天数
			if (endTime.isAfter(LocalDateTime.now())) {
				if (duration == 0) {
					memberActivateEntity.setDuration(duration);
				} else {
					memberActivateEntity.setDuration(memberActivateEntity.getDuration() + duration);
				}
			}

			//过期的场合，startTime 改为今天，然后续期
			else {
				memberActivateEntity.setStartTime(LocalDateTime.now());
				memberActivateEntity.setDuration(duration);
			}
			//开通纠错大师
			memberActivateEntity.setStatus("1");
			memberActivateMapper.updateById(memberActivateEntity);

			returnMap.put("updateResult", Boolean.FALSE);

			returnMap.put("msg", "续期成功");

			if (SecurityUtils.getUser() != null) {
				//记录操作人
				String username = SecurityUtils.getUser().getUsername();
				SysActLogZebra sysActLogZebra = new SysActLogZebra();
				//创建时间
				sysActLogZebra.setCreateTime(LocalDateTime.now());
				//操作人信息
				sysActLogZebra.setCreateUser(username);
				//目标用户ID
				sysActLogZebra.setMemberId(memberId);
				//类型
				sysActLogZebra.setType("2");
				//时长
				sysActLogZebra.setDuration(duration);
				adminFeignService.saveZebraLog(sysActLogZebra);
			}

			return new R(CommonConstants.SUCCESS, "续期成功", true);
		} else {

			MemberActivateEntity entity = new MemberActivateEntity();
			entity.setOrgId(orgId);
			String code = "TY" + IdUtil.simpleUUID().substring(0, 8).toUpperCase();
			while (haveRepeat(code)) {
				code = "TY" + IdUtil.simpleUUID().substring(0, 8).toUpperCase();
			}
			entity.setActvCode(code);
			entity.setUdid(udid);
			entity.setMemberId(memberId);
			entity.setDuration(duration);
			//开通体验状态设为4
			entity.setStatus("4");
			entity.setStartTime(LocalDateTime.now());
			entity.setSpecialType(2);
			entity.setType("1");
			//999999代表总部
			optId = (optId == null || optId.length() == 0) ? "999999" : optId;
			entity.setOptrId(Integer.parseInt(optId));

			memberActivateMapper.insert(entity);
			//用户绑定运营商
			MemberEntity memberEntity = new MemberEntity();
			memberEntity.setId(memberId);
			memberEntity.setOptId(Integer.valueOf(optId));
			memberMapper.updateById(memberEntity);
			Map returnMap = new HashMap();
			returnMap.put("updateResult", Boolean.FALSE);
			returnMap.put("msg", "激活成功");

			if (SecurityUtils.getUser() != null) {
				//记录操作人
				String username = SecurityUtils.getUser().getUsername();
				SysActLogZebra sysActLogZebra = new SysActLogZebra();
				//创建时间
				sysActLogZebra.setCreateTime(LocalDateTime.now());
				//操作人信息
				sysActLogZebra.setCreateUser(username);
				//目标用户ID
				sysActLogZebra.setMemberId(memberId);
				//类型
				sysActLogZebra.setType("2");
				//时长
				sysActLogZebra.setDuration(duration);
				adminFeignService.saveZebraLog(sysActLogZebra);
			}

			return new R(CommonConstants.SUCCESS, "激活成功", returnMap);
		}
	}

	/**
	 * 绑定激活码到用户，并且激活用户纠错大师权限
	 *
	 * @param udid
	 * @param code
	 * @param memberId
	 * @param orgId
	 * @param optId
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public R activateByCode(String udid, String code, String memberId, String orgId, String optId) {
		try {
			QueryWrapper queryWrapper = new QueryWrapper<>();
			queryWrapper.eq("actv_code", code);
			MemberActivateEntity memberActivateEntity = memberActivateMapper
					.selectOne(queryWrapper);
			//查询激活码是否存在
			if (memberActivateEntity != null) {
				//看是否开通过体验
				List<MemberActivateEntity> entityList = memberActivateMapper.selectList(
						new QueryWrapper<MemberActivateEntity>()
								.eq("member_id", memberId).orderByAsc("start_time"));

				if (entityList.size() >= 1 && isListAllTY(entityList)) {
					//说明开通过体验(可能延期过体验)，但从未正式激活过
					//此时，必须和体验的时候绑定的运营商一致，若不一致，则不让绑定
					if (!optId.equals(entityList.get(0).getOptrId())) {
						new R<>(Boolean.FALSE,
								MessageCodeEnum.MASTER_ERROR_128.getMessage())
								.setCode(MessageCodeEnum.MASTER_ERROR_128.getCode());
					}
				}

				//查询激活码是否已经被使用(为NUll未被使用)
				if (org.apache.commons.lang.StringUtils
						.isEmpty(memberActivateEntity.getMemberId())) {
					memberActivateEntity.setOrgId(orgId);
					memberActivateEntity.setUpdateTime(LocalDateTime.now());
					memberActivateEntity.setUdid(udid);
					memberActivateEntity.setMemberId(memberId);
					//如果之前激活还未过期，这里开始时间应该为上一次激活的EndTime
					memberActivateEntity.setStartTime(LocalDateTime.now());

					if (optId != null) {
						memberActivateEntity.setOptrId(Integer.parseInt(optId));
						memberActivateEntity.setStatus("1");
						//用户绑定运营商
						MemberEntity memberEntity = new MemberEntity();
						memberEntity.setId(memberId);
						memberEntity.setOptId(Integer.valueOf(optId));
						memberMapper.updateById(memberEntity);
					} else if (orgId != null) {
						memberActivateEntity.setStatus("1");
						//如果是机构开通，则绑定机构对应运营商，机构无对应运营商，则绑定总部
						OptOrg optOrg = optOrgMapper.selectOne(
								new QueryWrapper<OptOrg>().eq("org_id", orgId));
						if (optOrg == null) {
							//999999表示总部
							memberActivateEntity.setOptrId(999999);
						} else {
							optId = String.valueOf(optOrg.getOptId());
							memberActivateEntity.setOptrId(Integer.parseInt(optId));
							//用户绑定运营商
							MemberEntity memberEntity = new MemberEntity();
							memberEntity.setId(memberId);
							memberEntity.setOptId(Integer.valueOf(optId));
							memberMapper.updateById(memberEntity);
						}
					} else {
						//表示是总部激活
						memberActivateEntity.setOptrId(999999);
						memberActivateEntity.setStatus("3");
					}

					saveOrUpdate(memberActivateEntity);

					//Feign分配会员权限
					MemberEntity member = memberService.getById(memberId);
					//Map<String, Object> request = new HashMap<>();
					//request.put("phone", member.getPhone());
					//request.put("useTime", memberActivateEntity.getDuration());
					//remoteMemberService.addVipMember(request);

					//增加套餐额外的赠送内容
					addComboContentForActivation(memberActivateEntity.getComboId(), memberId,
							member);
				} else {
					return new R<>(Boolean.FALSE, MessageCodeEnum.MASTER_ERROR_127.getMessage())
							.setCode(MessageCodeEnum.MASTER_ERROR_127.getCode());
				}
			} else {
				return new R<>(Boolean.FALSE, MessageCodeEnum.MASTER_ERROR_126.getMessage())
						.setCode(MessageCodeEnum.MASTER_ERROR_126.getCode());
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return new R<>(Boolean.FALSE, MessageCodeEnum.MASTER_ERROR_129.getMessage());
		}

		return new R<>(Boolean.TRUE, MessageCodeEnum.SUCCESS.getMessage());
	}

	/**
	 * 绑定激活码到用户，并且激活用户纠错大师权限
	 *
	 * @param startTime
	 * @param udid
	 * @param code
	 * @param memberId
	 * @param orgId
	 * @param optId
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public R activateByCode(String startTime, String udid, String code, String memberId,
			String orgId, Integer optId, Integer duration) {

		QueryWrapper queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("actv_code", code);
		MemberActivateEntity memberActivateEntity = memberActivateMapper.selectOne(queryWrapper);
		//查询激活码是否存在
		if (memberActivateEntity != null) {
			//看是否开通过体验·
//				List<MemberActivateEntity> entityList = memberActivateMapper.selectList(
//						new QueryWrapper<MemberActivateEntity>()
//								.eq("member_id", memberId).orderByAsc("start_time"));

//				if (entityList.size() >= 1 && isListAllTY(entityList)) {
//					//说明开通过体验(可能延期过体验)，但从未正式激活过
//					//此时，必须和体验的时候绑定的运营商一致，若不一致，则不让绑定
//					if (!optId.equals(entityList.get(0).getOptrId())) {
//						new R<>(Boolean.FALSE,
//								MessageCodeEnum.MASTER_ERROR_128.getMessage())
//								.setCode(MessageCodeEnum.MASTER_ERROR_128.getCode());
//					}
//				}

			//查询激活码是否已经被使用(为NUll未被使用)
			if (org.apache.commons.lang.StringUtils.isEmpty(memberActivateEntity.getMemberId())) {

				memberActivateEntity.setOrgId(orgId);
				memberActivateEntity.setUpdateTime(LocalDateTime.now());
				memberActivateEntity.setUdid(udid);
				memberActivateEntity.setMemberId(memberId);

				if (startTime != null && !"".equals(startTime)) {

					//转换 startTime 为 LocalDateTime 格式
					DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
					if (startTime != null && startTime.length() == 10) {
						startTime = startTime + " 00:00:00";
					}
					LocalDateTime ldt = LocalDateTime.parse(startTime, df);

					memberActivateEntity.setStartTime(ldt);

				} else {
					//如果之前激活还未过期，这里开始时间应该为上一次激活的EndTime
					memberActivateEntity.setStartTime(LocalDateTime.now());
				}

				if (optId != null) {
					memberActivateEntity.setOptrId(optId);
					memberActivateEntity.setStatus("1");
					//用户绑定运营商
					MemberEntity memberEntity = new MemberEntity();
					memberEntity.setId(memberId);
					memberEntity.setOptId(Integer.valueOf(optId));
					memberMapper.updateById(memberEntity);
				} else if (orgId != null) {
					memberActivateEntity.setStatus("1");
					//如果是机构开通，则绑定机构对应运营商，机构无对应运营商，则绑定总部
					OptOrg optOrg = optOrgMapper.selectOne(
							new QueryWrapper<OptOrg>().eq("org_id", orgId));
					if (optOrg == null) {
						//999999表示总部
						memberActivateEntity.setOptrId(999999);
					} else {
						optId = optOrg.getOptId();
						memberActivateEntity.setOptrId(optId);
						//用户绑定运营商
						MemberEntity memberEntity = new MemberEntity();
						memberEntity.setId(memberId);
						memberEntity.setOptId(Integer.valueOf(optId));
						memberMapper.updateById(memberEntity);
					}
				} else {
					//表示是总部激活
					memberActivateEntity.setOptrId(999999);
					memberActivateEntity.setStatus("3");
				}

				saveOrUpdate(memberActivateEntity);

				//Feign分配会员权限
				MemberEntity member = memberService.getById(memberId);

				//2021-04-07 运营商后台 - 运营管理 - 智能设备开通
				if (duration != null && duration != 0) {
					Map<String, Object> request = new HashMap<>();
					request.put("phone", member.getPhone());
					request.put("useTime", memberActivateEntity.getDuration());
					remoteMemberService.addVipMember(request);
				}

				// 更新硬件码对应的运营商
				Map<String, Object> request = new HashMap<>();
				request.put("udid", udid);
				request.put("optId", optId);

				R res = remoteOptService.updUdid(request);

				if (res.getCode() == 1) {
					throw new BusinessException(res.getMsg());
				}

				//增加套餐额外的赠送内容
				addComboContentForActivation(memberActivateEntity.getComboId(), memberId, member);
			} else {
				throw new BusinessException(MessageCodeEnum.MASTER_ERROR_127.getMessage());
			}
		} else {
			throw new BusinessException(MessageCodeEnum.MASTER_ERROR_126.getMessage());
		}

		return new R<>(Boolean.TRUE, MessageCodeEnum.SUCCESS.getMessage());
	}

	@Override
	public R generateCode(Integer duration, Integer num, String comment, Integer comboId,
			Integer optId, Integer orgId) {
		//结果数组
		List<String> result = new ArrayList<>();
		for (int i = 0; i < num; i++) {
			if (duration == 0) {
				//永久码即为销售码
				MemberActivateEntity entity = new MemberActivateEntity();
				String code = "XS" + IdUtil.simpleUUID().substring(0, 8).toUpperCase()
						.replaceAll("0", "B").replaceAll("O", "G");
				while (haveRepeat(code)) {
					code = "XS" + IdUtil.simpleUUID().substring(0, 8).toUpperCase()
							.replaceAll("0", "B").replaceAll("O", "G");
				}
				entity.setActvCode(code);
				entity.setType("1");
				entity.setDuration(duration);
				entity.setSpecialType(2);
				entity.setStatus("0");
				entity.setComment(comment);

				if (null == optId) {
					//表示总部生成
					entity.setOptrId(999999);
				} else if (null != orgId) {
					entity.setOrgId(orgId.toString());
				} else {
					entity.setOptrId(optId);
				}

				if (comboId != null) {
					entity.setComboId(comboId);
				}

				if (save(entity)) {
					result.add(entity.getActvCode());
				}
			} else {
				//租赁码
				MemberActivateEntity entity = new MemberActivateEntity();
				String code = "ZL" + IdUtil.simpleUUID().substring(0, 8).toUpperCase()
						.replaceAll("0", "B").replaceAll("O", "G");
				while (haveRepeat(code)) {
					code = "ZL" + IdUtil.simpleUUID().substring(0, 8).toUpperCase()
							.replaceAll("0", "B").replaceAll("O", "G");
				}
				entity.setActvCode(code);
				entity.setType("1");
				entity.setDuration(duration);
				entity.setSpecialType(2);
				entity.setStatus("0");
				entity.setComment(comment);

				if (null == optId) {
					//表示总部生成
					entity.setOptrId(999999);
				} else if (null != orgId) {
					entity.setOrgId(orgId.toString());
				} else {
					entity.setOptrId(optId);
				}

				if (comboId != null) {
					entity.setComboId(comboId);
				}

				if (save(entity)) {
					result.add(entity.getActvCode());
				}
			}
		}
		return new R<>(result);
	}

	@Override
	public R isMaster(String memberId) {

		List<MemberActivateEntity> list = super.list(Wrappers.<MemberActivateEntity>query().lambda()
				.eq(MemberActivateEntity::getMemberId,
						memberId).orderByAsc(MemberActivateEntity::getUpdateTime));

		LocalDateTime dateTime = null;

		Map<String, Object> map = new HashMap<>();

		if (list.size() > 0) {

			map.put("status", 1);

			for (int i = 0; i < list.size(); i++) {

				if (i == list.size() - 1) {
					map.put("udid", list.get(i).getUdid());
				}

				if (list.get(i).getDuration() == 0) {
					map.put("time", 0);
					return new R<>(map, MessageCodeEnum.SUCCESS.getMessage());
				} else {
					//有效日期不为空
					if (null != dateTime) {
						//比较创建时间是否在有效期之后
						if (dateTime.isBefore(list.get(i).getUpdateTime()) || dateTime
								.isEqual(list.get(i).getUpdateTime())) {
							//在创建时间基础上添加时间
							dateTime = list.get(i).getUpdateTime()
									.plusDays(list.get(i).getDuration());
						} else {
							Duration duration = Duration
									.between(list.get(i).getUpdateTime(), dateTime);
							long days = duration.toDays() + list.get(i).getDuration();
							dateTime = list.get(i).getUpdateTime().plusDays(days);
						}
					} else {
						dateTime = list.get(i).getUpdateTime();
						dateTime = dateTime.plusDays(list.get(i).getDuration());
					}
				}
			}

			if (LocalDateTime.now().isBefore(dateTime)) {
				//返回激活时间还剩下多少天
				map.put("daysLeft", Duration.between(LocalDateTime.now(), dateTime).toDays());
			} else {
				//已过期
				map.put("status", 2);
			}
			map.put("time", dateTime.toString());
			return new R<>(map, MessageCodeEnum.SUCCESS.getMessage());
		} else {
			map.put("status", 0);
			map.put("time", -1);
			return new R<>(map, MessageCodeEnum.SUCCESS.getMessage());
		}
	}

	@Override
	public R getAllocateActivation(Page page, String phone, String code, String orgId, String optId,
			String duration, String startDate, String endDate) {
		IPage<JoyMasterDTO> result = memberActivateMapper
				.selectActivation(page, phone, code, orgId, optId, duration, startDate, endDate);
		return new R<>(result);
	}

	@Override
	public R getAllocateActivationByOpt(Page page, String phone, String udid, Integer optId,
			Integer orgId) {
		return new R<>(
				memberActivateMapper.selectActivationByOptr(page, phone, udid, orgId, optId));
	}

	@Override
	public R getAllActivation(Page page, String phone, String code, String duration) {
//		IPage<MemberActivateEntity> result = memberActivateMapper.selectPage(page, new QueryWrapper<MemberActivateEntity>());
		IPage<JoyMasterDTO> result = memberActivateMapper
				.selectAllActivation(page, phone, code, duration);
		return new R<>(result);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public R setActivationCountByOrg(String orgId, String updatePerson,
			Map<Object, Object> durationMap) {
		Map returnMap = new HashMap();

		List<OrgGoodsVO> masterList = baseMapper.getMasterStock(Integer.valueOf(orgId));

		if (masterList == null || masterList.size() == 0) {
			for (Map.Entry entry : durationMap.entrySet()) {
				boolean updateRes = memberActivateMapper.insertOrgActivationCount(
						orgId, (String) entry.getKey(), (int) entry.getValue());
				if (!updateRes) {
					returnMap.put("insertResult", false);
					return new R<>(returnMap);
				}

				LineProductUpdateRecord recordEntity = new LineProductUpdateRecord();
				recordEntity.setAssignAmount((int) entry.getValue());
				recordEntity.setOrgId(Integer.valueOf(orgId));
				recordEntity.setProductId(Integer.valueOf((String) entry.getKey()));
				boolean isStudio =
						organizationMapper.selectById(orgId).getBusinessLicense() != null ? false
								: true;
				recordEntity.setStudio(isStudio);
				SnowFlakeUtil snowFlake = new SnowFlakeUtil(2, 3);
				long assignId = snowFlake.nextId();
				recordEntity.setAssignId(String.valueOf(assignId));
				recordEntity.setCreateTime(new Date());
				recordEntity.setCreatedBy(updatePerson);
				lineProductUpdateRecordMapper.insert(recordEntity);
			}
		} else {
			for (Map.Entry entry : durationMap.entrySet()) {
				boolean updateRes = memberActivateMapper.updateOrgActivationCount(
						orgId, (String) entry.getKey(), (int) entry.getValue());
				if (!updateRes) {
					returnMap.put("updateResult", false);
					return new R<>(returnMap);
				}

				LineProductUpdateRecord recordEntity = new LineProductUpdateRecord();
				recordEntity.setAssignAmount((int) entry.getValue());
				recordEntity.setOrgId(Integer.valueOf(orgId));
				recordEntity.setProductId(Integer.valueOf((String) entry.getKey()));
				boolean isStudio =
						organizationMapper.selectById(orgId).getBusinessLicense() != null ? false
								: true;
				recordEntity.setStudio(isStudio);
				SnowFlakeUtil snowFlake = new SnowFlakeUtil(2, 3);
				long assignId = snowFlake.nextId();
				recordEntity.setAssignId(String.valueOf(assignId));
				recordEntity.setCreateTime(new Date());
				recordEntity.setCreatedBy(updatePerson);
				lineProductUpdateRecordMapper.insert(recordEntity);
			}
		}

		returnMap.put("updateResult", true);

		return new R<>(returnMap);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public R setActivationCountByOptr(String optrId, Map<Object, Object> durationMap) {
		Map returnMap = new HashMap();
		for (Map.Entry entry : durationMap.entrySet()) {
			boolean updateRes = memberActivateMapper
					.updateOptrActivationCount(optrId, (String) entry.getKey(),
							(int) entry.getValue());
			if (!updateRes) {
				returnMap.put("updateResult", false);
				return new R<>(returnMap);
			}

			LineProductUpdateRecord recordEntity = new LineProductUpdateRecord();
			recordEntity.setAssignAmount((int) entry.getValue());
			recordEntity.setOrgId(Integer.valueOf(optrId));
			recordEntity.setProductId(Integer.valueOf((String) entry.getKey()));
			lineProductUpdateRecordMapper.insert(recordEntity);
		}

		returnMap.put("updateResult", true);

		return new R<>(returnMap);
	}

	@Override
	public R getOrgCountRecord(String orgId) {
		List<LineProductUpdateRecord> recordsList = lineProductUpdateRecordMapper.selectList(
				new QueryWrapper<LineProductUpdateRecord>().eq(
						"org_id", orgId).orderByDesc("create_time"));
		if (recordsList == null || recordsList.size() == 0) {
			return new R<>(
					new ArrayList<com.shycloud.mido.opter.api.entity.LineProductUpdateRecord>(),
					"Record NOT found!");
		}

		//选择最新的5条记录
		recordsList = recordsList.size() >= 5 ? recordsList.subList(0, 5) : recordsList;

		return new R<>(recordsList);
	}

	@Override
	public R getStudioCountRecord(String orgId) {
		QueryWrapper wrapper = new QueryWrapper<LineProductUpdateRecord>();
		wrapper.eq("org_id", orgId);
		wrapper.eq("isStudio", 1);
		return new R<>(lineProductUpdateRecordMapper.selectList(wrapper));
	}

	@Override
	public R getOptrCountRecord(String optrId) {
		return new R<>(lineProductUpdateRecordMapper.selectList(
				new QueryWrapper<LineProductUpdateRecord>().eq("opt_id", optrId)));
	}

	/**
	 * app端激活纠错大师
	 *
	 * @param udid
	 * @param actvCode
	 * @param memberId
	 * @return java.lang.Boolean
	 * @author nianhua.jiang
	 * @date 2020/6/18 9:53
	 */
	@Override
	public R addActivationForApp(String udid, String actvCode, String memberId) {

		//查询【设备码】和【激活码】相对应的激活信息
		MemberActivateEntity memberActivateEntity = memberActivateMapper
				.selectOne(new QueryWrapper<MemberActivateEntity>()
						.eq("actv_code", actvCode)
						.eq("status", "1"));

		if (memberActivateEntity == null) {
			return new R(CommonConstants.FAIL, "激活码尚未开通", false);
		} else if (StringUtils.isNotEmpty(memberActivateEntity.getMemberId())) {
			return new R(CommonConstants.FAIL, "激活码已被使用", false);
		} else {
			//member id
			memberActivateEntity.setMemberId(memberId);

			if (!memberActivateEntity.getActvCode().equals(memberActivateEntity.getUdid())) {
				//设备码
				memberActivateEntity.setUdid(udid);
				//开始日期
				memberActivateEntity.setStartTime(LocalDateTime.now());
				//备注
				memberActivateEntity.setComment("纠错大师激活");
				//硬件
				memberActivateEntity.setType("1");
				//重要:这里用户的码一定是从运营商获取，用户无法直接从总部获取激活码!
				memberActivateEntity.setStatus("1");
			}

			if (memberActivateEntity.getSpecialType() == 3) {
				//开始日期
				memberActivateEntity.setStartTime(LocalDateTime.now());
			}

			//更新日期
			memberActivateEntity.setUpdateTime(LocalDateTime.now());
			//更新人
			memberActivateEntity.setUpdatedBy(memberId);

			MemberEntity member = memberService.getById(memberId);
			//增加套餐额外的赠送内容
			addComboContentForActivation(memberActivateEntity.getComboId(), memberId, member);
			//更新操作
			return new R(memberActivateMapper.updateById(memberActivateEntity));
		}
	}

	/**
	 * 续费纠错大师
	 *
	 * @param udid
	 * @param actvCode
	 * @param memberId
	 * @return com.shycloud.mido.common.core.util.R
	 * @author nianhua.jiang
	 * @date 2020/6/18 15:32
	 */
	@Override
	public R prolongMaster(String udid, String actvCode, String memberId, LocalDateTime startTime) {

		//查询激活码是否已经被使用
		MemberActivateEntity memberActivateEntity = memberActivateMapper
				.selectOne(new QueryWrapper<MemberActivateEntity>()
						.eq("actv_code", actvCode));

		if (memberActivateEntity == null) {
			return new R(CommonConstants.FAIL, "激活码不存在", false);
		}

		//判断激活码
		else {

			//已经有人使用过了激活码
			if (StringUtils.isNotEmpty(memberActivateEntity.getMemberId())) {
				return new R(CommonConstants.FAIL, "激活码已被使用", false);
			}

			//没被使用且存在此激活码
			else {

				//开始时间
				memberActivateEntity.setStartTime(startTime);
				//更新人
				memberActivateEntity.setUpdatedBy(memberId);
				//设备码
				memberActivateEntity.setUdid(udid);
				//创建时间
				memberActivateEntity.setCreateTime(LocalDateTime.now());
				//member_id
				memberActivateEntity.setMemberId(memberId);
				//状态，已分配
				memberActivateEntity.setStatus("1");
				//纠错大师
				memberActivateEntity.setType("1");
				//注释
				memberActivateEntity.setComment("纠错大师续费");
				//更新日期
				memberActivateEntity.setUpdateTime(LocalDateTime.now());

				MemberEntity member = memberService.getById(memberId);
				//增加套餐额外的赠送内容
				addComboContentForActivation(memberActivateEntity.getComboId(), memberId, member);

				//更新操作
				return new R(memberActivateMapper.updateById(memberActivateEntity));
			}
		}
	}

	/**
	 * 续费纠错大师 - 转销售之后的逻辑
	 *
	 * @param udid
	 * @param actvCode
	 * @return com.shycloud.mido.common.core.util.R
	 * @author nianhua.jiang
	 * @date 2020/6/18 15:32
	 */
	@Override
	public void prolongMasterMini(String udid, String actvCode, LocalDateTime startTime) {

		//查询硬件使用记录
		List<MemberActivateEntity> activateEntities = memberActivateMapper
				.selectList(new QueryWrapper<MemberActivateEntity>()
						.eq("actv_code", actvCode)
						.eq("status", "0")
						.orderByDesc("start_time"));

		//判断第一条记录是否有用户激活
		if (activateEntities.size() > 0 && activateEntities.get(0).getMemberId() != null) {
			//查找已经激活的设备信息
			MemberActivateEntity memberActivateEntity = memberActivateMapper
					.selectOne(new QueryWrapper<MemberActivateEntity>()
							.eq("actv_code", actvCode)
							.eq("status", "1"));
			//已经有人使用过了激活码
			if (StringUtils.isNotEmpty(memberActivateEntity.getMemberId())) {
				throw new BusinessException("此激活码已被他人使用");
			}
			//没被使用且存在此激活码
			else {

				//开始时间
				memberActivateEntity.setStartTime(startTime);
				//更新人
				memberActivateEntity.setUpdatedBy(activateEntities.get(0).getMemberId());
				//创建时间
				memberActivateEntity.setCreateTime(LocalDateTime.now());
				//member_id
				memberActivateEntity.setMemberId(activateEntities.get(0).getMemberId());
				//纠错大师
				memberActivateEntity.setType("1");
				//注释
				memberActivateEntity.setComment("转销售");
				//更新日期
				memberActivateEntity.setUpdateTime(LocalDateTime.now());

				MemberEntity member = memberService.getById(activateEntities.get(0).getMemberId());
				//增加套餐额外的赠送内容
				addComboContentForActivation(memberActivateEntity.getComboId(),
						activateEntities.get(0).getMemberId(), member);

				//更新操作
				memberActivateMapper.updateById(memberActivateEntity);
			}
		}
	}

	private boolean isListAllTY(List<MemberActivateEntity> entityList) {
		for (MemberActivateEntity entity : entityList) {
			if (!entity.getActvCode().startsWith("TY")) {
				return false;
			}
		}
		return true;
	}

	@Transactional(propagation = Propagation.REQUIRED)
	protected void addComboContentForActivation(Integer comboId, String memberId,
			MemberEntity entity) {
		//增加套餐额外的赠送内容
		if (comboId != null) {

			//获取虚拟币商品列表
			List<BasicGoodsInfo> goldGoodsList = remoteMemberService.matchGoodsInfoByKeyword("快乐贝");
			//获取打印卷商品列表
			List<BasicGoodsInfo> printCoupon = remoteMemberService.matchGoodsInfoByKeyword("打印劵");
			//获取VIP商品列表
			List<BasicGoodsInfo> printVip = remoteMemberService.matchGoodsInfoByKeyword("VIP");

			//套餐里的打印劵、快乐贝
			List<BasicComboGoods> goodsList = remoteMemberService.getGoodsByComboId(comboId);

			for (BasicComboGoods mapping : goodsList) {

				for (BasicGoodsInfo gold : goldGoodsList) {
					if (gold.getId() == mapping.getGoodsId()) {
						//增加快乐贝
						entity.setGold(
								entity.getGold() + gold.getUnitCount() * mapping.getQuantity());
						memberMapper.updateById(entity);
					}
				}

				for (BasicGoodsInfo print : printCoupon) {
					if (print.getId() == mapping.getGoodsId()) {
						//增加打印劵
						if (mapping.getGiftFlag().equals("0")) {
							entity.setPrintAmountBuy(
									entity.getPrintAmountBuy() + print.getUnitCount() * mapping
											.getQuantity());
						} else {
							entity.setPrintAmountGive(
									entity.getPrintAmountBuy() + print.getUnitCount() * mapping
											.getQuantity());
						}

						memberMapper.updateById(entity);
					}
				}

				for (BasicGoodsInfo vip : printVip) {

					if (vip.getId() == mapping.getGoodsId()) {
						//vip时长
						Integer vipDuration = vip.getExpireDuration() * mapping.getQuantity();

						MemberRole role = memberRoleMapper
								.selectOne(Wrappers.<MemberRole>query().lambda()
										.eq(MemberRole::getMemberId, memberId)
										.eq(MemberRole::getRoleCode, Constant.VIP_MEMBER));

						//如果此用户开过会员
						if (role != null) {

							LocalDateTime endTime = role.getEndTime();
							//若到期时间在今日之后，则正常延期
							if (role.getEndTime().isAfter(LocalDateTime.now())) {
								//延长期限
								role.setEndTime(endTime.plusDays(vipDuration));
							}

							//若到期时间在今天之前，那么需要更新开始日期以及结束日期
							else {
								role.setStartTime(LocalDateTime.now());
								role.setEndTime(LocalDateTime.now().plusDays(vipDuration));
							}
							memberRoleMapper.updMemberRole(role);
						}

						//若此用户没有开过会员
						else {
							MemberRole role2 = new MemberRole();
							role2.setCreateTime(LocalDateTime.now());
							role2.setStartTime(LocalDateTime.now());
							//开通会员天数
							role2.setEndTime(LocalDateTime.now().plusDays(vipDuration));
							role2.setRoleCode(Constant.VIP_MEMBER);
							role2.setMemberId(memberId);
							role2.setDelFlag(Constant.DEL_FLAG);
							memberRoleMapper.saveMemberRole(role2);
						}
					}

				}
			}
		}
	}


	/**
	 * 检查 udid 状态
	 *
	 * @param udid
	 * @return java.lang.String
	 * @author nianhua.jiang
	 * @date 2021/1/19 17:13
	 **/
	@Override
	public boolean checkUdid(String udid) {

		// 检查 udid 是否存在
		if (memberActivateMapper.checkIsUdid(udid) == 0) {
			return false;
		}

		//检查 udid 是否被使用
		List<MemberActivateEntity> activateList = memberActivateMapper
				.selectList(new QueryWrapper<MemberActivateEntity>().eq("udid", udid));

		if (activateList.size() > 0) {
			return false;
		}

		// 检查 UDID 是否已发货 status=1
		R udidDetail = remoteOptServiceV2.getUdidDetail(udid);

		Map<String, String> stockDeviceInfo = (Map<String, String>) udidDetail.getData();

		if ("1".equals(stockDeviceInfo.get("status"))) {
			throw new BusinessException("此硬件已发货");
		}

		return true;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public LocalDateTime activateByDurationMini(String udid, String busiType, String durationType,
			Integer durationTypeValue, String remark, Integer optId, Integer orgId,
			Integer distId, Integer specialType) {

		//计算激活时长
		Integer duration = null;

		if ("1".equals(durationType)) {
			//年
			duration = durationTypeValue * 365;
		} else if ("2".equals(durationType)) {
			//月
			duration = durationTypeValue * 30;
		} else if ("3".equals(durationType)) {
			duration = durationTypeValue;
		} else {
			throw new BusinessException("durationType参数不正确");
		}

		//查重
		List<MemberActivateEntity> memberActivateEntitys = memberActivateMapper
				.selectList(new QueryWrapper<MemberActivateEntity>()
						.eq("actv_code", udid)
						.eq("status", "1"));

		if (memberActivateEntitys.size() == 0) {

			//查询套餐 - 看是否有对应时长的 VIP 套餐 VIP商品ID = 21
			Integer comboId = remoteMemberServiceMini.checkCombGoods(21, duration);

			if (comboId == 0) {

				BasicComboInfo comboInfo = new BasicComboInfo();
				//套餐名
				comboInfo.setComboName("附赠" + duration + "天VIP套餐");
				//套餐类型
				comboInfo.setItemType("租赁");
				//纠错大师时长
				comboInfo.setHardwareDuration(duration);
				//VIP时长
				comboInfo.setVipDuration(duration);

				R resInsert = remoteMemberServiceMini.addComboMini(comboInfo);

				if (resInsert.getCode() == 1) {
					throw new BusinessException(resInsert.getMsg());
				}

				comboId = (Integer) resInsert.getData();

			}

			//新增激活码 = UDID
			MemberActivateEntity memberActivate = new MemberActivateEntity();
			//激活码
			memberActivate.setActvCode(udid);
			//时长
			memberActivate.setDuration(duration);
			//创建时间
			memberActivate.setCreateTime(LocalDateTime.now());
			//UDID
			memberActivate.setUdid(udid);
			//套餐ID
			memberActivate.setComboId(comboId);
			//备注
			memberActivate.setComment("小程序后台生成");
			//运营商ID
			memberActivate.setOptrId(optId);
			//机构ID
			memberActivate.setOrgId(orgId == null ? null : orgId.toString());
			//经销商ID
			memberActivate.setDistId(distId);
			//纠错大师
			memberActivate.setType("1");
			//开始时间
			memberActivate.setStartTime(LocalDateTime.now());
			//类型
			memberActivate.setBusiType(busiType);
			memberActivate.setDurationType(durationType);
			memberActivate.setDurationTypeValue(durationTypeValue);
			memberActivate.setRemark(remark);
			memberActivate.setSpecialType(specialType);
			//已使用
			memberActivate.setStatus("1");
			memberActivateMapper.insert(memberActivate);

			//处理硬件
			StockDeviceInfo stockDeviceInfo = new StockDeviceInfo();
			//设备码
			stockDeviceInfo.setUdid(udid);

			if ("1".equals(busiType)) {
				//已销售
				stockDeviceInfo.setActiveStatus("5");
			} else if ("2".equals(busiType)) {
				//出租
				stockDeviceInfo.setActiveStatus("4");
			} else if ("3".equals(busiType)) {
				//体验
				stockDeviceInfo.setActiveStatus("3");
			}
			//激活开始时间
			stockDeviceInfo.setActiveCreateTime(LocalDateTime.now());
			//激活更新时间
			stockDeviceInfo.setActiveUpdateTime(LocalDateTime.now());
			remoteMemberServiceMini.updStockDeviceInfo(stockDeviceInfo);

		}
		return LocalDateTime.now().plusDays(duration);
	}

	@Override
	public LocalDateTime activateByDurationMiniSale(String udid, String busiType,
			String durationType, Integer durationTypeValue, String remark, Integer optId,
			Integer orgId, Integer distId) {

		LocalDateTime localDateTime = activateByDurationMini(udid, busiType, durationType,
				durationTypeValue, remark, optId,
				orgId, distId, 1);

		//续费
		prolongMasterMini(udid, udid, LocalDateTime.now());

		return localDateTime;
	}
}

